package com.blue.alipay.controller;

import com.alibaba.fastjson.JSON;
import com.alipay.demo.trade.utils.ZxingUtils;
import com.blue.alipay.contants.WeXinConfig;
import com.blue.alipay.utils.controller.BaseController;
import com.blue.alipay.utils.date.DateUtil;
import com.blue.alipay.utils.http.HttpClientsUtil;
import com.blue.alipay.utils.http.XMLUtil;
import com.blue.alipay.utils.sign.WxSignature;
import com.blue.alipay.utils.ssl.SSLConSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import java.io.File;
import java.util.*;
import java.util.concurrent.ConcurrentSkipListMap;

/**
 * @描述 扫码下单
 * @时间 2017-9-27 15:26
 * @作者 肖亦鸣
 */
@Controller
@RequestMapping("wx_facepay")
public class WeXinFacePayController extends BaseController {
    private static Logger logger = LogManager.getLogger(WeXinFacePayController.class.getName());

    private final String PATH = "wx_facepay/";

    @RequestMapping("index.html")
    public String index() throws Exception {
        logger.info("index...");
        return PATH + "index";
    }

    @RequestMapping("precreate.html")
    public String precreate() throws Exception {
        logger.info("precreate...");
        return PATH + "precreate";
    }

    @RequestMapping("doprecreate.html")
    public String doPrecreate() throws Exception {
        logger.info("doPrecreate...");
        SortedMap<String, String> paramMap = buildParamMap();
        //扫码支付
        paramMap.put("trade_type", "NATIVE");

        String resXml = execute(WeXinConfig.API_UNIFIEDORDER, paramMap, WeXinConfig.parterKey);
        Map<String, String> resMap = XMLUtil.XMLToMap(resXml);
        logger.info("resMap:{}", JSON.toJSONString(resMap));
        String realPath = request.getSession().getServletContext().getRealPath("/");
        File destFile = new File(realPath + "/upload/");
        if (!destFile.exists()) {
            destFile.mkdirs();
        }
        // 需要修改为运行机器上的路径
        String fileName = String.format("qr-%s.png", resMap.get("prepay_id"));
        String filePath = String.format(destFile.getPath() + "/qr-%s.png", resMap.get("prepay_id"));

        logger.info("destFile.getPath():" + destFile.getPath());
        logger.info("filePath:" + filePath);
        request.setAttribute("fileName", "upload/" + fileName);
        request.setAttribute("outTradeNo", paramMap.get("out_trade_no"));
        //生成二维码文件
        ZxingUtils.getQRCodeImge(resMap.get("code_url"), 256, filePath);
        return PATH + "precreate";
    }

    @RequestMapping("query.html")
    public String query() throws Exception {
        logger.info("query...");
        return PATH + "query";
    }

    @RequestMapping("doquery.html")
    public String doQuery() throws Exception {
        logger.info("doQuery...");
        logger.info("requestParams:{}", JSON.toJSONString(request.getParameterMap()));
        SortedMap<String, String> paramMap = new TreeMap<String, String>();
        //两个二选1
     //   paramMap.put("out_trade_no", request.getParameter("outTradeNo"));
        paramMap.put("transaction_id", request.getParameter("transactionId"));
        paramMap.put("appid", WeXinConfig.appId);
        paramMap.put("mch_id", WeXinConfig.mchId);
        paramMap.put("nonce_str", "kee0v91lnlijk8jym1jsywz2dwls3mkg");


        String resXml = execute(WeXinConfig.API_ORDERQUERY, paramMap, WeXinConfig.parterKey);
        Map<String, String> resMap = XMLUtil.XMLToMap(resXml);
        logger.info("resMap:{}", JSON.toJSONString(resMap));
        request.setAttribute("msg", JSON.toJSONString(resMap));
        request.setAttribute("outTradeNo", request.getParameter("outTradeNo"));
        request.setAttribute("transactionId", request.getParameter("transactionId"));

        return PATH + "query";
    }

    @RequestMapping("refund.html")
    public String refund() throws Exception {
        logger.info("refund...");
        return PATH + "refund";
    }

    @RequestMapping("dorefund.html")
    public String doRefund() throws Exception {
        logger.info("doRefund...");
        logger.info("requestParams:{}", JSON.toJSONString(request.getParameterMap()));
        SortedMap<String, String> paramMap = new TreeMap<>();
        // 应用id
        paramMap.put("appid", WeXinConfig.appId);
        // 商户号
        paramMap.put("mch_id", WeXinConfig.mchId);
        // 随机字符串
        paramMap.put("nonce_str", "kee0v91lnlijk8jym1jsywz2dwls3mkg");
        paramMap.put("out_trade_no", request.getParameter("outTradeNo"));
        paramMap.put("out_refund_no", request.getParameter("outRequestNo"));
        paramMap.put("total_fee", "1");
        paramMap.put("refund_fee", "1");
        paramMap.put("refund_fee_type", WeXinConfig.channelUnit);
        paramMap.put("refund_desc", "测试数据");
        paramMap.put("refund_account", "REFUND_SOURCE_UNSETTLED_FUNDS");
        // 由于退款接口需要证书，在这里设置SSL
        setSSLConnectionSocketFactory(SSLConSocketFactory.get(request.getSession().getServletContext().getRealPath("/")
                + "/apiclient_cert.p12", WeXinConfig.mchId));
        String resXml = execute(WeXinConfig.API_REFUND, paramMap, WeXinConfig.parterKey);
        Map<String, String> resMap = XMLUtil.XMLToMap(resXml);
        logger.info("resMap:{}", JSON.toJSONString(resMap));
        request.setAttribute("msg", JSON.toJSONString(resMap));
        request.setAttribute("outTradeNo", request.getParameter("outTradeNo"));
        request.setAttribute("outRequestNo", request.getParameter("outRequestNo"));



        return PATH + "refund";
    }

    @RequestMapping("refundquery.html")
    public String refundQuery() throws Exception {
        logger.info("refundQuery...");
        return PATH + "refund_query";
    }
    @RequestMapping("dorefundquery.html")
    public String doRefundQuery() throws Exception {
        logger.info("doRefundQuery...");
        logger.info("requestParams:{}", JSON.toJSONString(request.getParameterMap()));
        SortedMap<String, String> paramMap = new TreeMap<>();
        // 应用id
        paramMap.put("appid", WeXinConfig.appId);
        // 商户号
        paramMap.put("mch_id", WeXinConfig.mchId);
        // 随机字符串
        paramMap.put("nonce_str", "kee0v91lnlijk8jym1jsywz2dwls3mkg");
        paramMap.put("out_trade_no", request.getParameter("outTradeNo"));
        paramMap.put("transaction_id", request.getParameter("transactionId"));
        paramMap.put("out_refund_no", "");
        paramMap.put("refund_id", "");
        // 由于退款接口需要证书，在这里设置SSL
        String resXml = execute(WeXinConfig.API_REFUNDQUERY, paramMap, WeXinConfig.parterKey);
        Map<String, String> resMap = XMLUtil.XMLToMap(resXml);
        logger.info("resMap:{}", JSON.toJSONString(resMap));
        request.setAttribute("msg", JSON.toJSONString(resMap));
        request.setAttribute("outTradeNo", request.getParameter("outTradeNo"));
        request.setAttribute("transactionId", request.getParameter("transactionId"));

        return PATH + "refund_query";
    }


    private static SortedMap<String, String> buildParamMap() {
        SortedMap<String, String> paramMap = new TreeMap<String, String>();
        // 应用id
        paramMap.put("appid", WeXinConfig.appId);
        // 商户号
        paramMap.put("mch_id", WeXinConfig.mchId);
        // 随机字符串
        paramMap.put("nonce_str", "kee0v91lnlijk8jym1jsywz2dwls3mkg");
        // 商品标题
        paramMap.put("body", "body_测试商品0.01元");
        paramMap.put("detail", "detail_测试商品0.01元");
        // 商户订单号
        paramMap.put("out_trade_no", "" + new Random().nextInt(88888888) + new Random().nextInt(999999999));
        // 总金额(单位分)
        paramMap.put("total_fee", "1");
        // 终端IP
        paramMap.put("spbill_create_ip", "10.253.8.233");
        // 下面设置交易过期时间：如果不传则设为半小时
        Date currentDate = new Date();
        // 交易起始时间
        paramMap.put("time_start", DateUtil.formatDate(currentDate, DateUtil.YYYYMMDDHHmmss));
        // 交易结束时间
        Calendar calender = Calendar.getInstance();
        calender.setTime(currentDate);
        calender.add(Calendar.MINUTE, 30);
        paramMap.put("time_expire", DateUtil.formatDate(calender.getTime(), DateUtil.YYYYMMDDHHmmss));
        // 自定义支付参数
        String customPayParam = "orderId=132468798798";
        // 异步通知接口
        String notifyUrl = WeXinConfig.notify_url + "?" + customPayParam;
        paramMap.put("notify_url", notifyUrl);
        // 二维码中包含的商品ID (扫码支付必传)
        paramMap.put("product_id", "79874621564812145");

        return paramMap;
    }

    public String execute(String url, SortedMap<String, String> paramMap, String parterKey) {
        // 生成签名
        String sign = WxSignature.generate(paramMap, parterKey);
        paramMap.put("sign", sign);
        logger.info("request wechat api " + url + " params: {}", JSON.toJSONString(paramMap));
        // 将请求参数转换为xml格式
        String reqXml = XMLUtil.mapToXML(paramMap);
        String resp;
        long start = System.currentTimeMillis();
        // 发送请求
        // 不需要证书
        if (sslcsf == null) {
            resp = HttpClientsUtil.httpClientPost(url, reqXml);
        }
        // 需要证书
        else {
            resp = HttpClientsUtil.httpClientSLLPost(sslcsf, url, reqXml);
        }
        long end1 = System.currentTimeMillis();
        logger.info("request wechat api " + url + " cost " + (end1 - start) + " ms. response: {}", resp);
        return resp;
    }

    private SSLConnectionSocketFactory sslcsf;

    public void setSSLConnectionSocketFactory(SSLConnectionSocketFactory sslcsf) {
        this.sslcsf = sslcsf;
    }

}
